﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using QuickGraph;
using QuickGraph.Serialization;
using QuickGraph.Serialization.DirectedGraphML;

namespace CrmWorkflowDependencies.Dependencies
{
    /// <summary>
    /// http://quickgraph.codeplex.com/discussions/207030    
    /// http://msdn.microsoft.com/en-us/library/vstudio/ee842619.aspx
    /// </summary>
    public static class DgmlExtensions
    {
        public static Vertex AddOrFind(this BidirectionalGraph<Vertex, Edge<Vertex>> graph, Vertex newvertex)
        {
            var newv = graph.Vertices.FirstOrDefault(v => v.Equals(newvertex));
            if (newv == null)
            {
                graph.AddVertex(newvertex);
                return newvertex;
            }
            return newv;
        }

        public static void ExportDgml(this IVertexAndEdgeListGraph<Vertex, Edge<Vertex>> graph, string graphname)
        {
            DirectedGraph dg = graph.ToDirectedGraphML(
                delegate(Vertex v)
                {
                    /// Vertex Identity
                    if(v is VertexProperty)
                    {
                        var p = ((VertexProperty)v).Parent;
                        return string.Concat(p == null ? "" : p.Alias, ".", v.Alias);
                    }
                    else
                    {
                        return v.Alias;
                    }

                },
                delegate(Edge<Vertex> edge)
                { 
                    /// Edge identity
                    //return string.Concat(edge.Source.Alias, "->", edge.Target.Alias);
                    return null;
                },
                delegate(Vertex v, DirectedGraphNode dgn) /// Vertex format
                {                    
                    dgn.Label = v.Label;

                    //dgn.Icon

                    /// если это "родительская" нода
                    //if (!(v is VertexProperty) && graph.Vertices.Where(gv => gv is VertexProperty).OfType<VertexProperty>().Count(gvp => gvp.Parent == v) > 0)
                    //{
                    //    /// переделать в группу
                    //    dgn.Group = GroupEnum.Expanded;
                    //    dgn.GroupSpecified = true;
                    //}

                    dgn.Category1 = v.Type.ToString();

                    if (v.Type == componenttype.Entity || graph.Vertices.Where(gv => gv is VertexProperty).OfType<VertexProperty>().Count(gvp => gvp.Parent == v) > 0)
                    {
                        dgn.Group = GroupEnum.Collapsed;
                        dgn.GroupSpecified = true;
                    }
                    
                    /// если Entity, то группа
                    if(v.Type == componenttype.Attribute)
                    {
                        
                    }

                    dgn.Reference = v.Url;
                    if (string.IsNullOrEmpty(v.Url))
                    {
                        if (v.Type == componenttype.Workflow)
                        {
                            dgn.Reference = string.Format("http://crm/cryptopro/sfa/workflow/edit.aspx?id={0}", v.ID);
                        }
                    }
                },
                delegate(Edge<Vertex> e, DirectedGraphLink dgl) /// Edge format
                {
                    if (e is CategoryEdge)
                    {
                        var ce = (CategoryEdge)e;
                        dgl.Category1 = ce.Category;
                    }
                    else
                    {
                        dgl.Category1 = string.Concat(e.Source.Type, " -> ", e.Target.Type);
                    }
                    if (e is MyEdge)
                    {
                        var me = (MyEdge)e;
                        if (!string.IsNullOrEmpty(me.Label))
                        {
                            dgl.Label = me.Label;
                        }
                    }
                    if (e.Source.Type == componenttype.Workflow && e.Target.Type == componenttype.Workflow)
                    { 
                        /// связь БП
                        //dgl.Background = "#FFFF7F7F";
                        //dgl.Stroke = "#FFFF7F7F";
                        dgl.AttractConsumers = ClrBoolean.True;
                        dgl.AttractConsumersSpecified = true;
                        //dgl.StrokeDashArray = "10,0";
                    }
                    if (e.Source.Type == componenttype.Attribute && e.Target.Type == componenttype.AttributePicklistValue)
                    { 
                        /// статус - значение
                        dgl.AttractConsumers = ClrBoolean.True;
                        dgl.AttractConsumersSpecified = true;
                    }

                }
            );

            dg.Properties = new DirectedGraphProperty[] { 
                new DirectedGraphProperty {
                    Id="WorkflowID",
                    IsReference = ClrBoolean.True,
                    IsReferenceSpecified = true,
                    Label = "URL формы",
                    DataType = "System.String",
                    ReferenceTemplate = "http://crm/cryptopro/sfa/workflow/edit.aspx?id={0}"
                }
            };

            dg.Categories = new[] { 
                new DirectedGraphCategory {
                    Id = string.Concat(componenttype.Workflow, " -> ", componenttype.AttributePicklistValue),
                    Background = "#FFFF7F7F",
                    Stroke = "#FFFF7F7F",
                    StrokeDashArray = "10,0"
                },
                new DirectedGraphCategory {
                    Id = string.Concat(componenttype.Workflow, " -> ", componenttype.Workflow),
                    Background = "#FFFF7F7F",
                    Stroke = "#FFFF7F7F",
                    StrokeDashArray = "10,0"
                },
                new DirectedGraphCategory { 
                    Id = componenttype.Workflow.ToString(),
                    Background = "#FFFF7F7F",
                    Label = "Бизнес-процесс",
                    
                    /// CanLinkedNodesBeDataDriven
                    /// https://github.com/peschuster/PropertyTranslator/blob/master/src/Dependencies.dgml
                    
                    //dgn.LinesOfCode = 100;
                    //dgn.LinesOfCodeSpecified = true;
                    VerticalAlignment = VerticalAlignmentEnum.Top,
                    VerticalAlignmentSpecified = true,
                    //dgn.IsVertical = ClrBoolean.True;
                    //dgn.IsVerticalSpecified = true;
                    HorizontalAlignment = HorizontalAlignmentEnum.Left,
                    HorizontalAlignmentSpecified = true,
                    //dgn.FontWeight = FontWeightEnum.Bold;
                    //dgn.FontWeightSpecified = true;
                    //dgn.Description = "Бизнес-процесс";                        

                },
                new DirectedGraphCategory { 
                    Id = componenttype.Entity.ToString(),
                    Background = "#758CFF",
                    Label = "Сущность",
                },
                new DirectedGraphCategory { 
                    Id = componenttype.Attribute.ToString(),
                    Background = "#FFFF8E",
                    Label = "Атрибут",
                    FontSizeSpecified = true,
                    FontSize = 8,
                    Details = "test details",                    
                },
                new DirectedGraphCategory { 
                    Id = componenttype.EntityRelationship.ToString(),
                    Background = "#ADFFE7",
                    Label = "Отношение",
                },
                new DirectedGraphCategory { 
                    Id = componenttype.ManagedProperty.ToString(),
                    Background = "#C6FFD4",
                    Label = "Свойство",
                },
                new DirectedGraphCategory { 
                    Id = componenttype.AttributePicklistValue.ToString(),
                    Background = "#C6FFD4",
                    Label = "Значение пиклиста",
                },
            };

            dg.WriteXml(graphname);
        }
    }
}